bitkeeper revision 1.1159.94.1 (4158442dkfhj0Lw3hZW1w5YYKJA01g)
authorcl349@freefall.cl.cam.ac.uk <cl349@freefall.cl.cam.ac.uk>
Mon, 27 Sep 2004 16:47:41 +0000 (16:47 +0000)
committercl349@freefall.cl.cam.ac.uk <cl349@freefall.cl.cam.ac.uk>
Mon, 27 Sep 2004 16:47:41 +0000 (16:47 +0000)
Add support for block devices.

.rootkeys
netbsd-2.0-xen-sparse/sys/arch/xen/conf/XEN
netbsd-2.0-xen-sparse/sys/arch/xen/include/hypervisor.h
netbsd-2.0-xen-sparse/sys/arch/xen/include/xbdvar.h [new file with mode: 0644]
netbsd-2.0-xen-sparse/sys/arch/xen/xen/xbd.c

index 9d93980e45da7177bcc6a3932ee65ab5a887e86a..6ecc463f9b4eaf4f1199d50a83041d80738843ca 100644 (file)
--- a/.rootkeys
+++ b/.rootkeys
 413cb3b4bRsqiHQLTKEZk4-zOksf8A netbsd-2.0-xen-sparse/sys/arch/xen/include/hypervisor.h
 413cb3b4OqY83qI8GztIZGADpvrpSw netbsd-2.0-xen-sparse/sys/arch/xen/include/if_xennetvar.h
 413cb3b42GG0LffraTnpZKlSUq57wg netbsd-2.0-xen-sparse/sys/arch/xen/include/pmap.h
+41580792kPzxLiPb47k_GDEMSbAbzA netbsd-2.0-xen-sparse/sys/arch/xen/include/xbdvar.h
 413cb3b4F0ArkWVBRyspkw7ivfXihg netbsd-2.0-xen-sparse/sys/arch/xen/include/xen.h
 413cb3b4ullQud70n4JClwoEEUBh8Q netbsd-2.0-xen-sparse/sys/arch/xen/include/xenfunc.h
 413cb3b4y1Ffq8BOhbdSpn-fGmKuEg netbsd-2.0-xen-sparse/sys/arch/xen/include/xenpmap.h
index e54802263f2196c315968b576578211a2a7cc3ad..eece41d429124ed3a20d5410a7c466dc9efbe428 100644 (file)
@@ -132,10 +132,10 @@ npx0              at hypervisor?          # x86 math coprocessor
 xencons*       at hypervisor?          # Xen virtual console
 xennet*        at hypervisor?          # Xen virtual network interface
 
-#xbd*          at hypervisor?          # Xen virtual block device
-#wd*           at hypervisor?          # Xen vbd (wd identity)
-#sd*           at hypervisor?          # Xen vbd (sd identity)
-#cd*           at hypervisor?          # Xen vbd (cd identity)
+xbd*           at hypervisor?          # Xen virtual block device
+wd*            at hypervisor?          # Xen vbd (wd identity)
+sd*            at hypervisor?          # Xen vbd (sd identity)
+cd*            at hypervisor?          # Xen vbd (cd identity)
 
 #xenkbc*       at hypervisor?          # Xen Keyboard/Mouse Interface
 #pckbd*                at xenkbc?              # Keyboard
index 83a170485e12e103bfe9471e31c0de4b5c6f0c75..b906595275c39b40e3b3f71757887bac9ac40173 100644 (file)
@@ -59,6 +59,7 @@ struct xen_npx_attach_args {
 #include <machine/hypervisor-ifs/event_channel.h>
 #include <machine/hypervisor-ifs/io/domain_controller.h>
 #include <machine/hypervisor-ifs/io/netif.h>
+#include <machine/hypervisor-ifs/io/blkif.h>
 
 #undef u8
 #undef u16
diff --git a/netbsd-2.0-xen-sparse/sys/arch/xen/include/xbdvar.h b/netbsd-2.0-xen-sparse/sys/arch/xen/include/xbdvar.h
new file mode 100644 (file)
index 0000000..8c1c57c
--- /dev/null
@@ -0,0 +1,56 @@
+/* $NetBSD: xbdvar.h,v 1.5 2004/05/07 14:15:11 cl Exp $ */
+
+/*
+ *
+ * Copyright (c) 2004 Christian Limpach.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Christian Limpach.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef _XEN_XBDVAR_H_
+#define _XEN_XBDVAR_H_
+
+struct xbd_softc {
+       struct device           sc_dev;         /* base device glue */
+       struct dk_softc         sc_dksc;        /* generic disk interface */
+       unsigned long           sc_xd_device;   /* cookie identifying device */
+       struct dk_intf          *sc_di;         /* pseudo-disk interface */
+       struct simplelock       sc_slock;       /* our lock */
+       int                     sc_shutdown;    /* about to be removed */
+};
+
+struct xbd_attach_args {
+       const char              *xa_device;
+       vdisk_t                 *xa_xd;
+       struct dk_intf          *xa_dkintf;
+       struct sysctlnode       *xa_diskcookies;
+};
+
+int xbd_scan(struct device *, struct xbd_attach_args *, cfprint_t);
+
+#endif /* _XEN_XBDVAR_H_ */
index b72ffc95a19f2fbad97488a2aa1e74b62917f0bf..9cfab063a97e74df6cea7a7ecd82cabafec74ed9 100644 (file)
@@ -63,12 +63,15 @@ __KERNEL_RCSID(0, "$NetBSD: xbd.c,v 1.9.2.1 2004/05/22 15:59:11 he Exp $");
 
 #include <dev/dkvar.h>
 #include <machine/xbdvar.h>
+
 #include <machine/xen.h>
 #include <machine/hypervisor.h>
-#include <machine/hypervisor-ifs/hypervisor-if.h>
-#include <machine/hypervisor-ifs/vbd.h>
 #include <machine/evtchn.h>
+#include <machine/ctrl_if.h>
+
 
+static void    control_send(blkif_request_t *, blkif_response_t *);
+static void    send_interface_connect(void);
 
 static void xbd_attach(struct device *, struct device *, void *);
 static int xbd_detach(struct device *, int);
@@ -178,11 +181,13 @@ static dev_t xbd_cd_cdev_major;
 
 static int     xbdstart(struct dk_softc *, struct buf *);
 static int     xbd_response_handler(void *);
+#if 0
 static void    xbd_update_create_kthread(void *);
 static void    xbd_update_kthread(void *);
 static int     xbd_update_handler(void *);
+#endif
 
-static int     xbdinit(struct xbd_softc *, xen_disk_t *, struct dk_intf *);
+static int     xbdinit(struct xbd_softc *, vdisk_t *, struct dk_intf *);
 
 /* Pseudo-disk Interface */
 static struct dk_intf dkintf_esdi = {
@@ -346,18 +351,32 @@ static int bufq_users = 0;
 
 #define MAX_VBDS 64
 static int nr_vbds;
-static xen_disk_t *vbd_info;
+static vdisk_t *vbd_info;
+
+static blkif_ring_t *blk_ring = NULL;
+static BLKIF_RING_IDX resp_cons; /* Response consumer for comms ring. */
+static BLKIF_RING_IDX req_prod;  /* Private request producer.         */
+static BLKIF_RING_IDX last_req_prod;  /* Request producer at last trap. */
 
-static blk_ring_t *blk_ring = NULL;
-static BLK_RING_IDX resp_cons; /* Response consumer for comms ring. */
-static BLK_RING_IDX req_prod;  /* Private request producer.         */
-static BLK_RING_IDX last_req_prod;  /* Request producer at last trap. */
+#define STATE_CLOSED           0
+#define STATE_DISCONNECTED     1
+#define STATE_CONNECTED                2
+static unsigned int state = STATE_CLOSED;
+static unsigned int blkif_evtchn = 0;
+static unsigned int blkif_irq = 0;
+static unsigned int blkif_handle = 0;
 
-#define STATE_ACTIVE    0
-#define STATE_SUSPENDED 1
-#define STATE_CLOSED    2
-static unsigned int state = STATE_SUSPENDED;
+static int blkif_control_rsp_valid = 0;
+static blkif_response_t blkif_control_rsp;
 
+/** Network interface info. */
+struct xbd_ctrl {
+
+       cfprint_t xc_cfprint;
+       struct device *xc_parent;
+};
+
+static struct xbd_ctrl blkctrl;
 
 #define XBDUNIT(x)             DISKUNIT(x)
 #define GETXBD_SOFTC(_xs, x)   if (!((_xs) = getxbd_softc(x))) return ENXIO
@@ -396,70 +415,317 @@ getxbd_softc(dev_t dev)
 }
 
 static int
-get_vbd_info(xen_disk_t *disk_info)
+get_vbd_info(vdisk_t *disk_info)
 {
-       int err;
-       block_io_op_t op; 
+       vdisk_t *buf;
+       int nr;
+       blkif_request_t req;
+       blkif_response_t rsp;
+       paddr_t pa;
 
+       buf = (vdisk_t *)uvm_km_kmemalloc1(kmem_map, NULL,
+           PAGE_SIZE, PAGE_SIZE, UVM_UNKNOWN_OFFSET, 0);
+       pmap_extract(pmap_kernel(), (vaddr_t)buf, &pa);
        /* Probe for disk information. */
-       memset(&op, 0, sizeof(op)); 
-       op.cmd = BLOCK_IO_OP_VBD_PROBE; 
-       op.u.probe_params.domain = 0; 
-       op.u.probe_params.xdi.max = MAX_VBDS;
-       op.u.probe_params.xdi.disks = disk_info;
-       op.u.probe_params.xdi.count = 0;
-
-       err = HYPERVISOR_block_io_op(&op);
-       if (err) {
-               printf("WARNING: Could not probe disks (%d)\n", err);
-               DIAGPANIC(("get_vbd_info: Could not probe disks (%d)", err));
-               return -1;
+       memset(&req, 0, sizeof(req));
+       req.operation = BLKIF_OP_PROBE;
+       req.nr_segments = 1;
+       req.frame_and_sects[0] = xpmap_ptom_masked(pa) | 7;
+
+       control_send(&req, &rsp);
+       nr = rsp.status > MAX_VBDS ? MAX_VBDS : rsp.status;
+
+       if (rsp.status < 0)
+               printf("WARNING: Could not probe disks (%d)\n", rsp.status);
+
+       memcpy(disk_info, buf, nr * sizeof(vdisk_t));
+
+       uvm_km_free(kmem_map, (vaddr_t)buf, PAGE_SIZE);
+
+       return nr;
+}
+
+static struct xbd_attach_args *
+get_xbda(vdisk_t *xd)
+{
+
+       switch (XEN_MAJOR(xd->device)) {
+#if NSD > 0
+       case XEN_SCSI_DISK0_MAJOR:
+       case XEN_SCSI_DISK1_MAJOR ... XEN_SCSI_DISK7_MAJOR:
+       case XEN_SCSI_DISK8_MAJOR ... XEN_SCSI_DISK15_MAJOR:
+               if (xd->capacity == 0)
+                       return NULL;
+               return &sd_ata;
+       case XEN_SCSI_CDROM_MAJOR:
+               return &cd_ata;
+#endif
+#if NWD > 0
+       case XEN_IDE0_MAJOR:
+       case XEN_IDE1_MAJOR:
+       case XEN_IDE2_MAJOR:
+       case XEN_IDE3_MAJOR:
+       case XEN_IDE4_MAJOR:
+       case XEN_IDE5_MAJOR:
+       case XEN_IDE6_MAJOR:
+       case XEN_IDE7_MAJOR:
+       case XEN_IDE8_MAJOR:
+       case XEN_IDE9_MAJOR:
+               switch (VDISK_TYPE(xd->info)) {
+               case VDISK_TYPE_CDROM:
+                       return &cd_ata;
+               case VDISK_TYPE_DISK:
+                       if (xd->capacity == 0)
+                               return NULL;
+                       return &wd_ata;
+               default:
+                       return NULL;
+               }
+               break;
+#endif
+       default:
+               if (xd->capacity == 0)
+                       return NULL;
+               return &xbd_ata;
+       }
+       return NULL;
+}
+
+static void
+free_interface(void)
+{
+
+       /* Prevent new requests being issued until we fix things up. */
+       // simple_lock(&blkif_io_lock);
+       // recovery = 1;
+       state = STATE_DISCONNECTED;
+       // simple_unlock(&blkif_io_lock);
+
+       /* Free resources associated with old device channel. */
+       if (blk_ring) {
+               uvm_km_free(kmem_map, (vaddr_t)blk_ring, PAGE_SIZE);
+               blk_ring = NULL;
        }
 
-       return op.u.probe_params.xdi.count;
+       if (blkif_irq) {
+#if 0
+               free_irq(blkif_irq, NULL);
+#endif
+               blkif_irq = 0;
+       }
+
+       if (blkif_evtchn) {
+#if 0
+               unbind_evtchn_from_irq(blkif_evtchn);
+#endif
+               blkif_evtchn = 0;
+       }
+}
+
+static void
+close_interface(void){
+}
+
+static void
+disconnect_interface(void)
+{
+
+       if (blk_ring == NULL)
+               blk_ring = (blkif_ring_t *)uvm_km_kmemalloc1(kmem_map, NULL,
+                   PAGE_SIZE, PAGE_SIZE, UVM_UNKNOWN_OFFSET, 0);
+       memset(blk_ring, 0, PAGE_SIZE);
+       blk_ring->req_prod = blk_ring->resp_prod = resp_cons = req_prod =
+               last_req_prod = 0;
+       state = STATE_DISCONNECTED;
+       send_interface_connect();
 }
 
 static void
 reset_interface(void)
 {
-       block_io_op_t op; 
 
-       op.cmd = BLOCK_IO_OP_RESET;
-       if (HYPERVISOR_block_io_op(&op) != 0)
-               printf("xbd: Possible blkdev trouble: couldn't reset ring\n");
+       printf("Recovering virtual block device driver\n");
+       free_interface();
+       disconnect_interface();
 }
 
 static void
-init_interface(void)
+connect_interface(blkif_fe_interface_status_t *status)
 {
-       block_io_op_t op; 
+       // unsigned long flags;
+       struct xbd_attach_args *xbda;
+       vdisk_t *xd;
+       int i;
 
-       reset_interface();
+       blkif_evtchn = status->evtchn;
+       blkif_irq = bind_evtchn_to_irq(blkif_evtchn);
 
-       if (blk_ring == NULL) {
-               op.cmd = BLOCK_IO_OP_RING_ADDRESS;
-               (void)HYPERVISOR_block_io_op(&op);
+       event_set_handler(blkif_irq, &xbd_response_handler, NULL, IPL_BIO);
+       hypervisor_enable_irq(blkif_irq);
 
-               blk_ring = (blk_ring_t *)uvm_km_valloc_align(kernel_map,
-                   PAGE_SIZE, PAGE_SIZE);
-               pmap_kenter_ma((vaddr_t)blk_ring, op.u.ring_mfn << PAGE_SHIFT,
-                   VM_PROT_READ|VM_PROT_WRITE);
-               DPRINTF(XBDB_SETUP, ("init_interface: "
-                   "ring va %p and wired to %p\n",
-                   blk_ring, (void *)(op.u.ring_mfn << PAGE_SHIFT)));
+       /* Transition to connected in case we need to do 
+        *  a partition probe on a whole disk. */
+       state = STATE_CONNECTED;
 
-               blk_ring->req_prod = blk_ring->resp_prod =
-                       resp_cons = req_prod = last_req_prod = 0;
+       /* Probe for discs attached to the interface. */
+       // xlvbd_init();
+       MALLOC(vbd_info, vdisk_t *, MAX_VBDS * sizeof(vdisk_t),
+           M_DEVBUF, M_WAITOK);
+       memset(vbd_info, 0, MAX_VBDS * sizeof(vdisk_t));
+       nr_vbds  = get_vbd_info(vbd_info);
+       if (nr_vbds <= 0)
+               goto out;
 
-               event_set_handler(_EVENT_BLKDEV, &xbd_response_handler,
-                   NULL, IPL_BIO);
-               hypervisor_enable_event(_EVENT_BLKDEV);
+       for (i = 0; i < nr_vbds; i++) {
+               xd = &vbd_info[i];
+               xbda = get_xbda(xd);
+               if (xbda) {
+                       xbda->xa_xd = xd;
+                       config_found(blkctrl.xc_parent, xbda,
+                           blkctrl.xc_cfprint);
+               }
        }
 
-       __insn_barrier();
-       state = STATE_ACTIVE;
+#if 0
+       /* Kick pending requests. */
+       save_and_cli(flags);
+       // simple_lock(&blkif_io_lock);
+       kick_pending_request_queues();
+       // simple_unlock(&blkif_io_lock);
+       restore_flags(flags);
+#endif
+       return;
+
+ out:
+       FREE(vbd_info, M_DEVBUF);
+       vbd_info = NULL;
+       return;
+}
+
+static void
+unexpected(blkif_fe_interface_status_t *status)
+{
+
+       printf("Unexpected blkif status %d in state %d\n", 
+           status->status, state);
 }
 
+#if 0
+static struct device *
+find_device(vdisk_t *xd)
+{
+       struct device *dv;
+       struct xbd_softc *xs = NULL;
+
+       for (dv = alldevs.tqh_first; dv != NULL; dv = dv->dv_list.tqe_next) {
+               if (dv->dv_cfattach == NULL ||
+                   dv->dv_cfattach->ca_attach != xbd_attach)
+                       continue;
+               xs = (struct xbd_softc *)dv;
+               if (xd == NULL || xs->sc_xd_device == xd->device)
+                       break;
+       }
+       return dv;
+}
+#endif
+
+static void
+blkif_status(blkif_fe_interface_status_t *status)
+{
+
+       if (status->handle != blkif_handle) {
+               printf("Invalid blkif: handle=%u", status->handle);
+               return;
+       }
+
+       switch (status->status) {
+       case BLKIF_INTERFACE_STATUS_CLOSED:
+               switch (state) {
+               case STATE_CLOSED:
+                       unexpected(status);
+                       break;
+               case STATE_DISCONNECTED:
+               case STATE_CONNECTED:
+                       unexpected(status);
+                       close_interface();
+                       break;
+               }
+               break;
+
+       case BLKIF_INTERFACE_STATUS_DISCONNECTED:
+               switch (state) {
+               case STATE_CLOSED:
+                       disconnect_interface();
+                       break;
+               case STATE_DISCONNECTED:
+               case STATE_CONNECTED:
+                       unexpected(status);
+                       reset_interface();
+                       break;
+               }
+               break;
+
+       case BLKIF_INTERFACE_STATUS_CONNECTED:
+               switch (state) {
+               case STATE_CLOSED:
+                       unexpected(status);
+                       disconnect_interface();
+                       connect_interface(status);
+                       break;
+               case STATE_DISCONNECTED:
+                       connect_interface(status);
+                       break;
+               case STATE_CONNECTED:
+                       unexpected(status);
+                       connect_interface(status);
+                       break;
+               }
+               break;
+
+       case BLKIF_INTERFACE_STATUS_CHANGED:
+               switch (state) {
+               case STATE_CLOSED:
+               case STATE_DISCONNECTED:
+                       unexpected(status);
+                       break;
+               case STATE_CONNECTED:
+#if 0
+                       vbd_update();
+#endif
+                       break;
+               }
+               break;
+
+       default:
+               printf(" Invalid blkif status: %d\n", status->status);
+               break;
+       }
+}
+
+
+static void
+xbd_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
+{
+       switch (msg->subtype) {
+       case CMSG_BLKIF_FE_INTERFACE_STATUS:
+               if (msg->length != sizeof(blkif_fe_interface_status_t))
+                       goto parse_error;
+               blkif_status((blkif_fe_interface_status_t *)
+                   &msg->msg[0]);
+               break;        
+       default:
+               goto parse_error;
+       }
+
+       ctrl_if_send_response(msg);
+       return;
+
+ parse_error:
+       msg->length = 0;
+       ctrl_if_send_response(msg);
+}
+
+#if 0
 static void
 enable_update_events(struct device *self)
 {
@@ -468,22 +734,108 @@ enable_update_events(struct device *self)
        event_set_handler(_EVENT_VBD_UPD, &xbd_update_handler, self, IPL_BIO);
        hypervisor_enable_event(_EVENT_VBD_UPD);
 }
+#endif
 
 static void
 signal_requests_to_xen(void)
 {
-       block_io_op_t op; 
 
-       DPRINTF(XBDB_IO, ("signal_requests_to_xen: %d -> %d\n",
-           blk_ring->req_prod, MASK_BLK_IDX(req_prod)));
-       blk_ring->req_prod = MASK_BLK_IDX(req_prod);
+       DPRINTF(XBDB_IO, ("signal_requests_to_xen: %x -> %x\n",
+                   blk_ring->req_prod, req_prod));
+       blk_ring->req_prod = req_prod;
        last_req_prod = req_prod;
 
-       op.cmd = BLOCK_IO_OP_SIGNAL; 
-       HYPERVISOR_block_io_op(&op);
+       hypervisor_notify_via_evtchn(blkif_evtchn);
        return;
 }
 
+static void
+control_send(blkif_request_t *req, blkif_response_t *rsp)
+{
+       unsigned long flags;
+       struct xbdreq *xr;
+
+ retry:
+       while ((req_prod - resp_cons) == BLKIF_RING_SIZE) {
+               tsleep((caddr_t) &req_prod, PUSER | PCATCH,
+                   "blkfront", 0);
+       }
+
+       save_and_cli(flags);
+       // simple_lock(&blkif_io_lock);
+       if ((req_prod - resp_cons) == BLKIF_RING_SIZE) {
+               // simple_unlock(&blkif_io_lock);
+               restore_flags(flags);
+               goto retry;
+       }
+
+       blk_ring->ring[MASK_BLKIF_IDX(req_prod)].req = *req;    
+
+       GET_XBDREQ(xr);
+       blk_ring->ring[MASK_BLKIF_IDX(req_prod)].req.id = (unsigned long)xr;
+       // rec_ring[id].id = (unsigned long) req;
+
+       // translate_req_to_pfn( &rec_ring[id], req );
+
+       req_prod++;
+       signal_requests_to_xen();
+
+       // simple_unlock(&blkif_io_lock);
+       restore_flags(flags);
+
+       while (!blkif_control_rsp_valid) {
+               /* XXXcl: sleep/wakeup not ready yet - busy wait for now.
+                * interrupts are still of, so we pick up the control
+                * channel response on return from HYPERVISOR_yield().
+                */
+#if 0
+               tsleep((caddr_t)&blkif_control_rsp_valid, PUSER | PCATCH,
+                   "blkfront", 0);
+#else
+               HYPERVISOR_yield();
+#endif
+       }
+
+       memcpy(rsp, &blkif_control_rsp, sizeof(*rsp));
+       blkif_control_rsp_valid = 0;
+}
+
+/* Send a driver status notification to the domain controller. */
+static void
+send_driver_status(int ok)
+{
+       ctrl_msg_t cmsg = {
+               .type    = CMSG_BLKIF_FE,
+               .subtype = CMSG_BLKIF_FE_DRIVER_STATUS,
+               .length  = sizeof(blkif_fe_driver_status_t),
+       };
+       blkif_fe_driver_status_t *msg = (void*)cmsg.msg;
+    
+       msg->status = ok ? BLKIF_DRIVER_STATUS_UP : BLKIF_DRIVER_STATUS_DOWN;
+
+       ctrl_if_send_message_block(&cmsg, NULL, 0, 0);
+}
+
+/* Tell the controller to bring up the interface. */
+static void
+send_interface_connect(void)
+{
+       ctrl_msg_t cmsg = {
+               .type    = CMSG_BLKIF_FE,
+               .subtype = CMSG_BLKIF_FE_INTERFACE_CONNECT,
+               .length  = sizeof(blkif_fe_interface_connect_t),
+       };
+       blkif_fe_interface_connect_t *msg = (void*)cmsg.msg;
+       paddr_t pa;
+
+       pmap_extract(pmap_kernel(), (vaddr_t)blk_ring, &pa);
+
+       msg->handle = 0;
+       msg->shmem_frame = xpmap_ptom_masked(pa) >> PAGE_SHIFT;
+
+       ctrl_if_send_message_block(&cmsg, NULL, 0, 0);
+}
+
 static void
 setup_sysctl(void)
 {
@@ -514,62 +866,16 @@ setup_sysctl(void)
                diskcookies = pnode;
 }
 
-static struct xbd_attach_args *
-get_xbda(xen_disk_t *xd)
-{
-
-       switch (XEN_MAJOR(xd->device)) {
-#if NSD > 0
-       case XEN_SCSI_DISK0_MAJOR:
-       case XEN_SCSI_DISK1_MAJOR ... XEN_SCSI_DISK7_MAJOR:
-       case XEN_SCSI_DISK8_MAJOR ... XEN_SCSI_DISK15_MAJOR:
-               if (xd->capacity == 0)
-                       return NULL;
-               return &sd_ata;
-       case XEN_SCSI_CDROM_MAJOR:
-               return &cd_ata;
-#endif
-#if NWD > 0
-       case XEN_IDE0_MAJOR:
-       case XEN_IDE1_MAJOR:
-       case XEN_IDE2_MAJOR:
-       case XEN_IDE3_MAJOR:
-       case XEN_IDE4_MAJOR:
-       case XEN_IDE5_MAJOR:
-       case XEN_IDE6_MAJOR:
-       case XEN_IDE7_MAJOR:
-       case XEN_IDE8_MAJOR:
-       case XEN_IDE9_MAJOR:
-               switch (XD_TYPE(xd->info)) {
-               case XD_TYPE_CDROM:
-                       return &cd_ata;
-               case XD_TYPE_DISK:
-                       if (xd->capacity == 0)
-                               return NULL;
-                       return &wd_ata;
-               default:
-                       return NULL;
-               }
-               break;
-#endif
-       default:
-               if (xd->capacity == 0)
-                       return NULL;
-               return &xbd_ata;
-       }
-       return NULL;
-}
-
 int
 xbd_scan(struct device *self, struct xbd_attach_args *mainbus_xbda,
     cfprint_t print)
 {
        struct xbdreq *xr;
-       struct xbd_attach_args *xbda;
-       xen_disk_t *xd;
        int i;
 
-       init_interface();
+       blkctrl.xc_parent = self;
+       blkctrl.xc_cfprint = print;
+
        if (xen_start_info.flags & SIF_PRIVILEGED)
                setup_sysctl();
 
@@ -593,47 +899,23 @@ xbd_scan(struct device *self, struct xbd_attach_args *mainbus_xbda,
        xbd_cd_cdev_major = major(devsw_blk2chr(makedev(xbd_cd_major, 0)));
 #endif
 
-       MALLOC(xr, struct xbdreq *, BLK_RING_SIZE * sizeof(struct xbdreq),
+       MALLOC(xr, struct xbdreq *, BLKIF_RING_SIZE * sizeof(struct xbdreq),
            M_DEVBUF, M_WAITOK | M_ZERO);
 #ifdef DEBUG
        xbd_allxr = xr;
 #endif
-
-       /* XXX Xen1.2: We cannot use BLK_RING_SIZE many slots, since
-        * Xen 1.2 keeps indexes masked in the ring and the case where
-        * we queue all slots at once is handled wrong. 
-        */
-       for (i = 0; i < BLK_RING_SIZE - 1; i++)
+       for (i = 0; i < BLKIF_RING_SIZE - 1; i++)
                PUT_XBDREQ(&xr[i]);
 
-       MALLOC(vbd_info, xen_disk_t *, MAX_VBDS * sizeof(xen_disk_t),
-           M_DEVBUF, M_WAITOK);
-       memset(vbd_info, 0, MAX_VBDS * sizeof(xen_disk_t));
-       nr_vbds  = get_vbd_info(vbd_info);
-       if (nr_vbds <= 0)
-               goto out;
+       (void)ctrl_if_register_receiver(CMSG_BLKIF_FE, xbd_ctrlif_rx,
+           CALLBACK_IN_BLOCKING_CONTEXT);
 
-       for (i = 0; i < nr_vbds; i++) {
-               xd = &vbd_info[i];
-               xbda = get_xbda(xd);
-               if (xbda) {
-                       xbda->xa_xd = xd;
-                       config_found(self, xbda, print);
-               }
-       }
+       send_driver_status(1);
 
+#if 0
        enable_update_events(self);
-
-       return 0;
-
- out:
-       FREE(vbd_info, M_DEVBUF);
-       vbd_info = NULL;
-       FREE(xr, M_DEVBUF);
-#ifdef DEBUG
-       xbd_allxr = NULL;
 #endif
-       SLIST_INIT(&xbdreqs);
+
        return 0;
 }
 
@@ -844,20 +1126,21 @@ fill_ring(struct xbdreq *xr)
        paddr_t pa;
        unsigned long ma;
        vaddr_t addr, off;
-       blk_ring_req_entry_t *ring_req;
-       int breq, nr_sectors;
+       blkif_request_t *ring_req;
+       int breq, nr_sectors, fsect, lsect;
 
        /* Fill out a communications ring structure. */
-       ring_req = &blk_ring->ring[MASK_BLK_IDX(req_prod)].req;
+       ring_req = &blk_ring->ring[MASK_BLKIF_IDX(req_prod)].req;
        ring_req->id = (unsigned long)xr;
-       ring_req->operation = pxr->xr_bp->b_flags & B_READ ? XEN_BLOCK_READ :
-               XEN_BLOCK_WRITE;
-       ring_req->sector_number = (xen_sector_t)pxr->xr_bn;
+       ring_req->operation = pxr->xr_bp->b_flags & B_READ ? BLKIF_OP_READ :
+               BLKIF_OP_WRITE;
+       ring_req->sector_number = pxr->xr_bn;
        ring_req->device = pxr->xr_sc->sc_xd_device;
 
        DPRINTF(XBDB_IO, ("fill_ring(%d): bp %p sector %llu pxr %p xr %p\n",
-           MASK_BLK_IDX(req_prod), pxr->xr_bp, (unsigned long long)pxr->xr_bn,
-           pxr, xr));
+                   MASK_BLKIF_IDX(req_prod), pxr->xr_bp,
+                   (unsigned long long)pxr->xr_bn,
+                   pxr, xr));
 
        xr->xr_breq = 0;
        ring_req->nr_segments = 0;
@@ -870,7 +1153,7 @@ fill_ring(struct xbdreq *xr)
 #else
                pmap_extract(pmap_kernel(), addr, &pa);
 #endif
-               ma = xpmap_ptom_masked(pa) + off;
+               ma = xpmap_ptom_masked(pa);
                DIAGCONDPANIC((ma & (XEN_BSIZE - 1)) != 0,
                    ("xbd request ma not sector aligned"));
 
@@ -878,23 +1161,29 @@ fill_ring(struct xbdreq *xr)
                        breq = PAGE_SIZE - off;
                else
                        breq = pxr->xr_bqueue;
+
                nr_sectors = breq >> XEN_BSHIFT;
                DIAGCONDPANIC(nr_sectors >= XEN_BSIZE,
                    ("xbd request nr_sectors >= XEN_BSIZE"));
 
+               fsect = off >> XEN_BSHIFT;
+               lsect = fsect + nr_sectors - 1;
+               DIAGCONDPANIC(fsect > 7, ("xbd request fsect > 7"));
+               DIAGCONDPANIC(lsect > 7, ("xbd request lsect > 7"));
+
                DPRINTF(XBDB_IO, ("fill_ring(%d): va 0x%08lx pa 0x%08lx "
                    "ma 0x%08lx, sectors %d, left %ld/%ld\n",
-                   MASK_BLK_IDX(req_prod), addr, pa, ma, nr_sectors,
+                   MASK_BLKIF_IDX(req_prod), addr, pa, ma, nr_sectors,
                    pxr->xr_bqueue >> XEN_BSHIFT, pxr->xr_bqueue));
 
-               ring_req->buffer_and_sects[ring_req->nr_segments++] =
-                       ma | nr_sectors;
+               ring_req->frame_and_sects[ring_req->nr_segments++] =
+                       ma | (fsect<<3) | lsect;
                addr += PAGE_SIZE;
                pxr->xr_bqueue -= breq;
                pxr->xr_bn += nr_sectors;
                xr->xr_breq += breq;
                off = 0;
-               if (ring_req->nr_segments == MAX_BLK_SEGS)
+               if (ring_req->nr_segments == BLKIF_MAX_SEGMENTS_PER_REQUEST)
                        break;
        }
        pxr->xr_data = addr;
@@ -1048,64 +1337,81 @@ xbd_response_handler(void *arg)
 {
        struct buf *bp;
        struct xbd_softc *xs;
-       blk_ring_resp_entry_t *ring_resp;
+       blkif_response_t *ring_resp;
        struct xbdreq *pxr, *xr;
-       int i;
+       BLKIF_RING_IDX i, rp;
 
-       for (i = resp_cons; i != blk_ring->resp_prod; i = BLK_RING_INC(i)) {
-               ring_resp = &blk_ring->ring[MASK_BLK_IDX(i)].resp;
+       rp = blk_ring->resp_prod;
+       __insn_barrier(); /* Ensure we see queued responses up to 'rp'. */
+
+       for (i = resp_cons; i != rp; i++) {
+               ring_resp = &blk_ring->ring[MASK_BLKIF_IDX(i)].resp;
                xr = (struct xbdreq *)ring_resp->id;
-               pxr = xr->xr_parent;
-
-               DPRINTF(XBDB_IO, ("xbd_response_handler(%d): pxr %p xr %p "
-                   "bdone %04lx breq %04lx\n", i, pxr, xr, pxr->xr_bdone,
-                   xr->xr_breq));
-               pxr->xr_bdone -= xr->xr_breq;
-               DIAGCONDPANIC(pxr->xr_bdone < 0,
-                   ("xbd_response_handler: pxr->xr_bdone < 0"));
-
-               if (__predict_false(ring_resp->status)) {
-                       pxr->xr_bp->b_flags |= B_ERROR;
-                       pxr->xr_bp->b_error = EIO;
-               }
 
-               if (xr != pxr) {
-                       PUT_XBDREQ(xr);
-                       if (!SIMPLEQ_EMPTY(&xbdr_suspended))
-                               xbdresume();
-               }
+               switch (ring_resp->operation) {
+               case BLKIF_OP_READ:
+               case BLKIF_OP_WRITE:
+                       pxr = xr->xr_parent;
+
+                       DPRINTF(XBDB_IO, ("xbd_response_handler(%d): pxr %p "
+                                   "xr %p bdone %04lx breq %04lx\n", i, pxr,
+                                   xr, pxr->xr_bdone, xr->xr_breq));
+                       pxr->xr_bdone -= xr->xr_breq;
+                       DIAGCONDPANIC(pxr->xr_bdone < 0,
+                           ("xbd_response_handler: pxr->xr_bdone < 0"));
+
+                       if (__predict_false(ring_resp->status)) {
+                               pxr->xr_bp->b_flags |= B_ERROR;
+                               pxr->xr_bp->b_error = EIO;
+                       }
 
-               if (pxr->xr_bdone == 0) {
-                       bp = pxr->xr_bp;
-                       xs = getxbd_softc(bp->b_dev);
-                       if (xs == NULL) { /* don't fail bp if we're shutdown */
-                               bp->b_flags |= B_ERROR;
-                               bp->b_error = EIO;
+                       if (xr != pxr) {
+                               PUT_XBDREQ(xr);
+                               if (!SIMPLEQ_EMPTY(&xbdr_suspended))
+                                       xbdresume();
                        }
-                       DPRINTF(XBDB_IO, ("xbd_response_handler(%d): "
-                           "completed bp %p\n", i, bp));
-                       if (bp->b_flags & B_ERROR)
-                               bp->b_resid = bp->b_bcount;
-                       else
-                               bp->b_resid = 0;
-
-                       if (pxr->xr_aligned)
-                               unmap_align(pxr);
-
-                       PUT_XBDREQ(pxr);
-                       if (xs)
-                               disk_unbusy(&xs->sc_dksc.sc_dkdev,
-                                   (bp->b_bcount - bp->b_resid),
-                                   (bp->b_flags & B_READ));
-                       biodone(bp);
-                       if (!SIMPLEQ_EMPTY(&xbdr_suspended))
-                               xbdresume();
-                       /* XXX possible lockup if this was the only
-                        * active device and requests were held back in
-                        * the queue.
-                        */
-                       if (xs)
-                               dk_iodone(xs->sc_di, &xs->sc_dksc);
+
+                       if (pxr->xr_bdone == 0) {
+                               bp = pxr->xr_bp;
+                               xs = getxbd_softc(bp->b_dev);
+                               if (xs == NULL) { /* don't fail bp if we're shutdown */
+                                       bp->b_flags |= B_ERROR;
+                                       bp->b_error = EIO;
+                               }
+                               DPRINTF(XBDB_IO, ("xbd_response_handler(%d): "
+                                           "completed bp %p\n", i, bp));
+                               if (bp->b_flags & B_ERROR)
+                                       bp->b_resid = bp->b_bcount;
+                               else
+                                       bp->b_resid = 0;
+
+                               if (pxr->xr_aligned)
+                                       unmap_align(pxr);
+
+                               PUT_XBDREQ(pxr);
+                               if (xs)
+                                       disk_unbusy(&xs->sc_dksc.sc_dkdev,
+                                           (bp->b_bcount - bp->b_resid),
+                                           (bp->b_flags & B_READ));
+                               biodone(bp);
+                               if (!SIMPLEQ_EMPTY(&xbdr_suspended))
+                                       xbdresume();
+                               /* XXX possible lockup if this was the only
+                                * active device and requests were held back in
+                                * the queue.
+                                */
+                               if (xs)
+                                       dk_iodone(xs->sc_di, &xs->sc_dksc);
+                       }
+                       break;
+               case BLKIF_OP_PROBE:
+                       memcpy(&blkif_control_rsp, ring_resp,
+                           sizeof(*ring_resp));
+                       blkif_control_rsp_valid = 1;
+                       wakeup((caddr_t)&blkif_control_rsp_valid);
+                       break;
+               default:
+                       panic("unknown response");
                }
        }
        resp_cons = i;
@@ -1115,23 +1421,7 @@ xbd_response_handler(void *arg)
        return 0;
 }
 
-static struct device *
-find_device(xen_disk_t *xd)
-{
-       struct device *dv;
-       struct xbd_softc *xs;
-
-       for (dv = alldevs.tqh_first; dv != NULL; dv = dv->dv_list.tqe_next) {
-               if (dv->dv_cfattach == NULL ||
-                   dv->dv_cfattach->ca_attach != xbd_attach)
-                       continue;
-               xs = (struct xbd_softc *)dv;
-               if (xs->sc_xd_device == xd->device)
-                       break;
-       }
-       return dv;
-}
-
+#if 0
 static void
 xbd_update_create_kthread(void *arg)
 {
@@ -1145,24 +1435,24 @@ xbd_update_kthread(void *arg)
        struct device *parent = arg;
        struct xbd_attach_args *xbda;
        struct device *dev;
-       xen_disk_t *xd;
-       xen_disk_t *vbd_info_update, *vbd_info_old;
+       vdisk_t *xd;
+       vdisk_t *vbd_info_update, *vbd_info_old;
        int i, j, new_nr_vbds;
        extern int hypervisor_print(void *, const char *);
 
-       MALLOC(vbd_info_update, xen_disk_t *, MAX_VBDS *
-           sizeof(xen_disk_t), M_DEVBUF, M_WAITOK);
+       MALLOC(vbd_info_update, vdisk_t *, MAX_VBDS *
+           sizeof(vdisk_t), M_DEVBUF, M_WAITOK);
 
        for (;;) {
-               memset(vbd_info_update, 0, MAX_VBDS * sizeof(xen_disk_t));
+               memset(vbd_info_update, 0, MAX_VBDS * sizeof(vdisk_t));
                new_nr_vbds  = get_vbd_info(vbd_info_update);
 
                if (memcmp(vbd_info, vbd_info_update, MAX_VBDS *
-                   sizeof(xen_disk_t)) == 0) {
+                   sizeof(vdisk_t)) == 0) {
                        FREE(vbd_info_update, M_DEVBUF);
                        tsleep(parent, PWAIT, "xbdupd", 0);
-                       MALLOC(vbd_info_update, xen_disk_t *, MAX_VBDS *
-                           sizeof(xen_disk_t), M_DEVBUF, M_WAITOK);
+                       MALLOC(vbd_info_update, vdisk_t *, MAX_VBDS *
+                           sizeof(vdisk_t), M_DEVBUF, M_WAITOK);
                        continue;
                }
 
@@ -1228,6 +1518,7 @@ xbd_update_handler(void *arg)
 
        return 0;
 }
+#endif
 
 /* XXX: we should probably put these into dksubr.c, mostly */
 int
@@ -1309,7 +1600,7 @@ xbddump(dev_t dev, daddr_t blkno, caddr_t va, size_t size)
 }
 
 static int
-xbdinit(struct xbd_softc *xs, xen_disk_t *xd, struct dk_intf *dkintf)
+xbdinit(struct xbd_softc *xs, vdisk_t *xd, struct dk_intf *dkintf)
 {
        struct dk_geom *pdg;
        char buf[9];